package com.xk.supply.utils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5 加密工具类
 * 线程安全实现
 */
public class MD5Util {
    
    private static final String MD5_ALGORITHM = "MD5";
    private static final char[] HEX_DIGITS = {
            '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };

    /**
     * 对字符串进行MD5加密（32位小写）
     * @param input 原始字符串
     * @return MD5加密后的字符串
     */
    public static String md5(String input) {
        if (input == null) {
            return null;
        }
        
        try {
            byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
            return md5(bytes);
        } catch (Exception e) {
            throw new RuntimeException("MD5加密失败", e);
        }
    }

    /**
     * 对字节数组进行MD5加密
     * @param bytes 原始字节数组
     * @return MD5加密后的字符串
     */
    public static String md5(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        
        try {
            MessageDigest digest = MessageDigest.getInstance(MD5_ALGORITHM);
            byte[] md5Bytes = digest.digest(bytes);
            return bytesToHex(md5Bytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不可用", e);
        }
    }

    /**
     * 对文件进行MD5加密
     * @param filePath 文件路径
     * @return 文件的MD5值
     */
    public static String md5File(String filePath) {
        // 实现文件MD5计算（这里省略具体实现）
        throw new UnsupportedOperationException("文件MD5计算未实现");
    }

    /**
     * 校验字符串与MD5值是否匹配
     * @param input 原始字符串
     * @param md5 MD5值
     * @return 是否匹配
     */
    public static boolean verify(String input, String md5) {
        if (input == null || md5 == null) {
            return false;
        }
        return md5.equalsIgnoreCase(md5(input));
    }

    /**
     * 字节数组转十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            sb.append(HEX_DIGITS[(b >> 4) & 0x0f]);
            sb.append(HEX_DIGITS[b & 0x0f]);
        }
        return sb.toString();
    }

    /**
     * 生成加盐MD5
     * @param input 原始字符串
     * @param salt 盐值
     * @return 加盐后的MD5
     */
    public static String md5WithSalt(String input, String salt) {
        if (input == null || salt == null) {
            return null;
        }
        return md5(input + salt);
    }
}